<!--
 * @页面名称:图片预览
 * @描述: 
 * @作者: 
 * @Date:
-->
<template>
  <div class="imageViewer">
    <el-container>
      <el-header>
        <div>
          行：<el-input-number
            v-model="rowVal"
            :min="1"
            :max="10"
            controls-position="right"
            @change="inputChange"
          ></el-input-number>
          列：<el-input-number
            v-model="colVal"
            :min="1"
            :max="10"
            controls-position="right"
            @change="inputChange"
          ></el-input-number>
        </div>
      </el-header>
      <el-container>
        <el-aside>
          <div class="show-preview">
            <div class="preview">
              <img :src="previews.url" />
            </div>
          </div>
        </el-aside>
        <el-main>
          <div class="row" v-for="item in rowVal" :key="item">
            <div class="col grid-content" v-for="item2 in colVal" :key="item2">
              <VueCropper
                ref="cropper"
                :img="option.img[item - 1][item2 - 1]"
                :outputSize="option.outputSize"
                :outputType="option.outputType"
                :info="option.info"
                :canScale="option.canScale"
                :autoCrop="option.autoCrop"
                :fixed="option.fixed"
                :fixedNumber="option.fixedNumber"
                :full="option.full"
                :fixedBox="option.fixedBox"
                :canMove="option.canMove"
                :canMoveBox="option.canMoveBox"
                :original="option.original"
                :centerBox="option.centerBox"
                :infoTrue="option.infoTrue"
                :maxImgSize="option.maxImgSize"
                :enlarge="option.enlarge"
                :mode="option.mode"
                @realTime="realTime"
                @click="click"
              ></VueCropper>
            </div>
          </div>
        </el-main>
      </el-container>
    </el-container>
    <div class="operationBar">
      <el-button class="btn" @click="reset">刷新</el-button>
      <el-button class="btn" @click="trimClick">裁剪</el-button>
      <el-button class="btn" @click="changeScale(1)">放大</el-button>
      <el-button class="btn" @click="changeScale(-1)">缩小</el-button>
      <el-button class="btn" @click="rotateLeft">左旋转</el-button>
      <el-button class="btn" @click="rotateRight">右旋转</el-button>
      <el-button class="btn" @click="clear">清除</el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed, nextTick } from "vue";
import "vue-cropper/dist/index.css";
import { VueCropper } from "vue-cropper";
// 获取点击的el元素
const el = ref();
// 行默认值
const rowVal = ref(4);
// 列默认值
const colVal = ref(6);
// 图片配置
const option = reactive({
  img: "", //裁剪图片的地址
  outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
  outputType: "jpeg", //裁剪生成图片的格式（jpeg || png || webp）
  info: true, //图片大小信息
  canScale: true, //图片是否允许滚轮缩放
  autoCrop: false, //是否默认生成截图框
  fixed: false, //是否开启截图框宽高固定比例
  fixedNumber: [1.53, 1], //截图框的宽高比例
  full: false, //false按原比例裁切图片，不失真
  fixedBox: false, //固定截图框大小，不允许改变
  canMove: true, //上传图片是否可以移动
  canMoveBox: true, //截图框能否拖动
  original: false, //上传图片按照原始比例渲染
  centerBox: false, //截图框是否被限制在图片里面
  infoTrue: false, //true为展示真实输出图片宽高，false展示看到的截图框宽高
  maxImgSize: 3000, //限制图片最大宽度和高度
  enlarge: 1, //图片根据截图框输出比例倍数
  mode: "contain" //图片默认渲染方式
});
// 预览裁切图片
const previews = reactive({
  url: "",
  img: ""
});
// 获取实例
const cropper = ref();

//实时预览函数
const realTime = () => {
  getBase64(el?.value);
};
// 获取截图
const getBase64 = (val?: any) => {
  val?.getCropBlob((data: any) => {
    previews.url = window.URL.createObjectURL(new Blob([data], { type: "application/zip" }));
  });
};
// 点击
const click = (e: any) => {
  if (e.target.__vueParentComponent.props.img && e.target.__vueParentComponent.props.autoCrop !== true) {
    e.target.__vueParentComponent.props.autoCrop = true;
    cropper.value.forEach((item: any) => {
      if (item.img === e.target.__vueParentComponent.props.img) {
        el.value = item;
        getBase64(item);
      }
    });
  } else {
    cropper.value.forEach((item: any) => {
      if (item.img === e.target.__vueParentComponent.props.img) {
        e.target.__vueParentComponent.props.autoCrop = false;
      }
    });
  }
};
// 点击裁剪
const trimClick = () => {
  cropper.value.forEach((item: any) => {
    if (item.img === el.value.img) {
      item.imgs = previews.url;
    }
  });
};
// 放大/缩小
const changeScale = (num: number) => {
  num = num || 1;
  el.value.changeScale(num);
};
// 左转
const rotateLeft = () => {
  el.value.rotateLeft();
};
// 右转
const rotateRight = () => {
  el.value.rotateRight();
};
// 重置
const reset = () => {
  cropper.value.forEach((item: any) => {
    item.refresh();
  });
  option.img = convertTo2DArray(arr, rowVal.value, colVal.value) as any;
};
// 清除框选
const clear = () => {
  el.value.refresh();
};
// 数组转换
const convertTo2DArray = (arr: string[], rows: number, cols: number) => {
  let result = [];
  for (let i = 0; i < rows; i++) {
    let row = [];
    for (let j = 0; j < cols; j++) {
      row.push(arr[i * cols + j]);
    }
    result.push(row);
  }
  return result;
};
const arr = [
  new URL("@/assets/images/test.jpeg", import.meta.url).href,
  new URL("@/assets/images/login_left.png", import.meta.url).href,
  new URL("@/assets/images/login_left1.png", import.meta.url).href,
  new URL("@/assets/images/login_left2.png", import.meta.url).href,
  new URL("@/assets/images/login_left3.png", import.meta.url).href,
  new URL("@/assets/images/login_left4.png", import.meta.url).href,
  new URL("@/assets/images/login_left5.png", import.meta.url).href
];
option.img = convertTo2DArray(arr, rowVal.value, colVal.value) as any;
// 输入框改变事件
const inputChange = () => {
  reset();
};
</script>

<style scoped lang="scss">
.imageViewer {
  height: 100%;
  width: 100%;
  display: flex;
  .operationBar {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 75px;
    height: 100%;
    border-left: 1px solid #efefef;
    .btn {
      width: 50px;
      margin: 0 0 5px 0;
    }
  }
  .el-header {
    padding: 0;
    height: 45px;
    line-height: 45px;
    background-color: rgb(199, 242, 242);
  }
  .el-container {
    height: calc(100% - 20px);
    .el-aside {
      width: 200px;
      background-color: #efefef;
      .preview img {
        object-fit: contain;
        width: 100%;
      }
    }
    .el-main {
      margin: 0 5px;
      padding: 5px;
      border: 1px solid #ccc;
      background-color: #efefef;
      height: 100%;
      .row {
        display: flex;
        justify-content: flex-start;
        .grid-content {
          width: calc(100% / v-bind("colVal"));
          border-radius: 4px;
          height: calc(calc(100vh - 180px) / v-bind("rowVal"));
          margin: 3px;
          background-color: bisque;
          :deep(img) {
            width: 100%;
            height: 100%;
            object-fit: contain;
          }
        }
      }
    }
  }
}
</style>
